package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.Product;
import cn.wolfcode.domain.SeckillProduct;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mapper.SeckillProductMapper;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.web.feign.ProductFeign;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by lanxw
 */
@Service
public class SeckillProductServiceImpl implements ISeckillProductService {
    @Autowired
    private SeckillProductMapper seckillProductMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ProductFeign productFeign;
    @Override
    public List<SeckillProductVo> getSeckillProductByTime(Integer queryByTime) {
//        查询秒杀数据的商品
        List<SeckillProduct> seckillProductList = seckillProductMapper.queryCurrentlySeckillProduct(queryByTime);
        if(seckillProductList.size()==0){
            return Collections.EMPTY_LIST;
        }
//        获取秒杀商品的id
        List<Long> ids=seckillProductList.stream().map(item->{
            return item.getProductId();
        }).collect(Collectors.toList());
//        远程调用获取商品列表
        Result<List<Product>> listResult = productFeign.queryByIds(ids);
        if(Objects.isNull(listResult) || listResult.hasError()){
            throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);
        }
        List<Product> productList=listResult.getData();
//        外部调用数据
        Map<Long, Product> productMap=new HashMap<>();
//        定义id和商品的映射关系
        for (Product product : productList) {
            productMap.put(product.getId(),product);
        }
//        重构数据vo并返回
        List<SeckillProductVo> list=new ArrayList<>();
        for (SeckillProduct seckillProduct : seckillProductList) {
            SeckillProductVo vo=new SeckillProductVo();
//            把seckillproduct的数据和product的数据封装到vo中
            Product product=productMap.get(seckillProduct.getProductId());
//            数据拷贝到vo对象中
            BeanUtils.copyProperties(product,vo);
            BeanUtils.copyProperties(seckillProduct,vo);
//            当前数据默认等于库存数量
            vo.setCurrentCount(seckillProduct.getStockCount());
            list.add(vo);
        }
        return list;
    }

    @Override
    public SeckillProductVo find(Integer time, Long seckillId) {
//        查询数据
        SeckillProduct seckillProduct= seckillProductMapper.find(seckillId);
        List<Long> ids=new ArrayList<>();
        ids.add(seckillProduct.getProductId());
        Result<List<Product>> result = productFeign.queryByIds(ids);
        if(Objects.isNull(result) || result.hasError()){
            throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);
        }
        Product product=result.getData().get(0);
//        将数据封装成vo对象
        SeckillProductVo vo =new SeckillProductVo() ;
        BeanUtils.copyProperties(product,vo);
        BeanUtils.copyProperties(seckillProduct,vo);
        return vo;
    }

    @Override
    public int decrStockCount(Long id) {
        int stock = seckillProductMapper.decrStock(id);
        return  stock;
    }

    @Override
    public List<SeckillProductVo> getSeckillProductByTimeFromCache(Integer time) {
        String key = SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(String.valueOf(time));
        List<Object> values = redisTemplate.opsForHash().values(key);
        List<SeckillProductVo> seckillProductVoList=new ArrayList<>();
        for (Object value : values) {
            seckillProductVoList.add(JSON.parseObject((String) value,SeckillProductVo.class));
        }
        return seckillProductVoList;
    }

    @Override
    public SeckillProductVo findFromCache(Integer time, Long seckillId) {
        String key = SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(String.valueOf(time));
        Object obj = redisTemplate.opsForHash().get(key, String.valueOf(seckillId));
        SeckillProductVo vo = JSON.parseObject((String) obj, SeckillProductVo.class);
        return vo;
    }

    @Override
    public void syncStockToRedis(Integer time, Long seckillId) {
        SeckillProduct seckillProduct= seckillProductMapper.find(seckillId);
                if(seckillProduct.getStockCount()>0){
                    String key = SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(String.valueOf(time));
                    redisTemplate.opsForHash().put(key,String.valueOf(seckillId),String.valueOf(seckillProduct.getStockCount()));
                }
    }

    @Override
    public void incrStockCount(Long seckillId) {
            seckillProductMapper.incrStock(seckillId);
    }
}
